<?php
require_once 'wxSign.php';

header('Content-type:text/html; Charset=utf-8');
class wxPay extends wxSign
{
    public $data = null;

    /**
     * 统一下单
     * @param string $openid openid
     * @param float  $totalFee 收款总费用 单位元
     * @param string $outTradeNo 唯一的订单号
     * @param string $orderName 订单名称
     * @param string $notifyUrl 支付结果通知url 不要有问号
     * @param string $attach 附加数据，原样返回【可选】
     * @param string $type 1：小程序支付，2：公众号支付【可选】
     * @return string
     */
    public function jsApi($openid, $totalFee, $outTradeNo, $orderName, $notifyUrl, $attach = '', $type = 1)
    {
        if ($type == 1) {
            //微信小程序支付
            if (empty($appid = $this->getXcxAppid())) apiReturn(2, '微信小程序APPID缺失');
        } else {
            //微信公众号支付
            if (empty($appid = $this->getGzhAppid())) apiReturn(2, '微信公众号APPID缺失');
        }
        if (empty($mch_id = $this->getMchId())) apiReturn(2, '商户号缺失');
        if (empty($mch_key = $this->getMchKey())) apiReturn(2, '商户号秘钥缺失');

        if (empty($openid)) apiReturn(2, 'OPENID缺失');
        if ($totalFee <= 0) apiReturn(2, '价格错误');
        if (empty($outTradeNo)) apiReturn(2, '订单号缺失');
        if (empty($notifyUrl)) apiReturn(2, '回调地址缺失');

        //$orderName = iconv('GBK','UTF-8',$orderName);
        $unified = array(
            'appid' => $appid,
            'attach' => $attach,//附加数据；原样返回，如果填写中文，请注意转换为utf-8
            'body' => $orderName,
            'mch_id' => $mch_id,
            'nonce_str' => self::createNonceStr(),
            'notify_url' => $notifyUrl,
            'openid' => $openid,
            'out_trade_no' => $outTradeNo,
            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
            'total_fee' => intval($totalFee * 100),       //单位 转为分
            'trade_type' => 'JSAPI',
        );
        $unified['sign'] = self::getSign($unified, $mch_key);
        $responseXml = self::curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', self::arrayToXml($unified));
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
        if ($unifiedOrder === false) {
            die('parse xml error');
        }
        if ($unifiedOrder->return_code != 'SUCCESS') {
            die($unifiedOrder->return_msg);
        }
        if ($unifiedOrder->result_code != 'SUCCESS') {
            die($unifiedOrder->err_code);
        }

        $pay_time = time();
        $data = array(
            "appId" => $appid,
            "timeStamp" => "$pay_time",//这里是字符串的时间戳，不是int，所以需加引号
            "nonceStr" => self::createNonceStr(),
            "package" => "prepay_id=" . $unifiedOrder->prepay_id,
            "signType" => 'MD5',
        );
        $data['paySign'] = self::getSign($data, $mch_key);
        return $data;
    }

    public static function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }

    public static function createNonceStr($length = 16)
    {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $str = '';
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    public static function curlGet($url = '', $options = array())
    {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }

    public static function curlPost($url = '', $postData = '', $options = array())
    {
        if (is_array($postData)) {
            $postData = http_build_query($postData);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
}